package com.gradle.quartz.batch.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.gradle.bean.user.User;
import com.gradle.quartz.batch.prestatement.UserPreStatementSetter;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;
import org.springframework.batch.item.json.JacksonJsonObjectMarshaller;
import org.springframework.batch.item.json.JacksonJsonObjectReader;
import org.springframework.batch.item.json.JsonFileItemWriter;
import org.springframework.batch.item.json.JsonItemReader;
import org.springframework.batch.item.json.builder.JsonFileItemWriterBuilder;
import org.springframework.batch.item.json.builder.JsonItemReaderBuilder;
import org.springframework.batch.item.support.CompositeItemWriter;
import org.springframework.batch.item.support.builder.CompositeItemWriterBuilder;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.PathResource;

import javax.sql.DataSource;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Arrays;

/**
 * 输出数据到多种文本
 *
 * @author ldanniel
 */
@Configuration
@EnableBatchProcessing
public class MultiTerminalConfig {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private DataSource druidDataSource;
    @Autowired
    private UserPreStatementSetter userPreStatementSetter;
    @Bean
    public JacksonJsonObjectMarshaller<User> multiMarshaller(){
        return new JacksonJsonObjectMarshaller<>();
    }
    @Bean
    public ItemWriter<User>  multiConsoleItemWriter() {
        return items -> {
            for (User item : items) {
                System.out.println(">>>>>>>>>>>>输出到控制台，user = [" + item + "]");
            }
        };
    }

    @Bean
    public FlatFileItemWriter<User> multiItemWriter()  {
        return new FlatFileItemWriterBuilder<User>()
                .name("userFlatItemWriter")
                .resource(new PathResource("D:\\workspace\\mygradleproject\\readerOut\\readerOut.txt"))
                //指定输出格式
                .formatted()
                .format("id:%s,姓名：%s,年龄：%s,联系地址:%s")
                .names("id", "userName", "age", "address")
                .build();
    }


    @Bean
    public JsonFileItemWriter<User> multiFlatItemWriter() {
        return new JsonFileItemWriterBuilder<User>()
                .name("userJsonItemWriter")
                .resource(new PathResource("D:\\workspace\\mygradleproject\\readerOut\\writerOut.json"))
                .jsonObjectMarshaller(multiMarshaller())
                .build();
    }

    @Bean
    public JdbcBatchItemWriter<User> multiJdbcItemWriter() {
        return new JdbcBatchItemWriterBuilder<User>()
                .dataSource(druidDataSource)
                .sql("insert into user(id,userName,age,address) values(?,?,?,?)")
                .itemPreparedStatementSetter(userPreStatementSetter)
                .build();
    }


    @Bean
    public JsonItemReader<User> multiJsonItemReader() throws FileNotFoundException {
        ObjectMapper objectMapper = new ObjectMapper();
        JacksonJsonObjectReader<User> userReader = new JacksonJsonObjectReader<>(User.class);
        userReader.setMapper(objectMapper);
        File file = new File("D:\\workspace\\mygradleproject\\gradle-quartz\\src\\main\\resources\\file\\user.json");
        return new JsonItemReaderBuilder<User>()
                .name("userJsonItemReader")
                .resource(new InputStreamResource(new FileInputStream(file)))
                .jsonObjectReader(userReader)
                .build();
    }

    /**
     * 处理任务的逻辑对象
     *
     * @return Tasklett
     */
    @Bean
    public Tasklet multiTaskLet() {
        return (contribution, chunkContext) -> {
            System.out.println(">>>>>>>>>jsonTaskLet->处理任务的逻辑对象【jsonTaskLet】>>>>>>>>");
            return RepeatStatus.FINISHED;
        };
    }

    @Bean
    public CompositeItemWriter<User> multiCompositeItemWriter() throws Exception {
       return new CompositeItemWriterBuilder<User>()
                .delegates(multiConsoleItemWriter(),multiFlatItemWriter(),multiJdbcItemWriter())
                .build();
    }

    @Bean
    public Step multiStep() throws Exception {
        System.out.println(">>>>>>>>>compositeStep-->【compositeStep】>>>>>>>>");
        return stepBuilderFactory.get("multiStep")
                //一次性读多少数据,以及数据类型为User
                .<User, User>chunk(1)
                .reader(multiJsonItemReader())
                .writer(multiCompositeItemWriter())
                .build();
    }

    @Bean
    public Job multiJob() throws Exception {
        System.out.println(">>>>>>>>>jsonJob--> 任务启动执行对象【compositeStepJob】>>>>>>>>");
        return jobBuilderFactory.get("composite-writer-job")
                .start(multiStep())
                .incrementer(new RunIdIncrementer())
                .build();
    }
}
